import 'dart:async';
import 'dart:typed_data';
import 'dart:ffi';
import 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:hello/hello.dart';
import 'package:flutter/widgets.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  String str = '';
  Uint8List bytes;
  PixelMemoryImage pixelMemoryImage;

  Future _load() async {
    String str1 = await Hello.platformVersion;
    Uint8List bytes1 = await Hello.getNativeImage(2);
    setState(() {
      _counter++;
      str = str1;
      bytes = bytes1;
    });
  }

  Future _loadBitmapPtr() async {
    Map<dynamic, dynamic> map = await Hello.getBitmapPtr();
    int pixelsDataAddress = map['pixelsDataAddress'];
    int pixelsDataWidth = map['pixelsDataWidth'];
    int pixelsDataHeight = map['pixelsDataHeight'];
    print('pixelsDataAddress=$pixelsDataAddress,pixelsDataWidth=$pixelsDataWidth,pixelsDataHeight=$pixelsDataHeight');
    Pointer<Uint8> pointer = Pointer<Uint8>.fromAddress(pixelsDataAddress);
    int bytesCount = pixelsDataHeight * pixelsDataWidth * 4;
    Uint8List bytes = pointer.asExternalTypedData(count: bytesCount);
    ui.PixelFormat format = ui.PixelFormat.rgba8888;
    setState(() {
      pixelMemoryImage = PixelMemoryImage(bytes, pixelsDataWidth, pixelsDataHeight, format);
    });
  }

  Future _loadPtr() async {
    Map<dynamic, dynamic> map = await Hello.getNativeImagePtr();
    int rawDataAddress = map['rawDataAddress'];
    int rawDataLength = map['rawDataLength'];
    print('rawDataAddress=$rawDataAddress,rawDataLength=$rawDataLength');
    Pointer<Uint8> pointer = Pointer<Uint8>.fromAddress(rawDataAddress); //address是内存地址
    Uint8List bytes1 = pointer.asExternalTypedData(count: rawDataLength);
    print('bytes1长度：${bytes1.length}');
//Uint8List bytes可以通过 Image.memory 接口显示图像
//建议参考MemoryImage重写一个ImageProvider把对native内存引用释放罗加入
//之前调用native获取指针，增加内存引用计数1
    PaintingBinding.instance.instantiateImageCodec(bytes1);
//之后通知减除内存引用1
    setState(() {
      bytes = bytes1;
    });
  }

  Future _delete() async {
    setState(() {
      _counter = 0;
      str = "";
      bytes = null;
      pixelMemoryImage = null;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '${str}You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
            bytes != null
                ? Image.memory(
                    bytes,
                    width: 200.0,
                    height: 200.0,
                    fit: BoxFit.contain,
                  )
                : Container(
                    color: Colors.red,
                    width: 200.0,
                    height: 200.0,
                  ),
            pixelMemoryImage != null
                ? new Image(
                    image: pixelMemoryImage,
                    width: 200.0,
                    height: 200.0,
                    fit: BoxFit.contain,
                  )
                : Container(
                    color: Colors.green,
                    width: 200.0,
                    height: 200.0,
                  ),
          ],
        ),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          FloatingActionButton(
            onPressed: _loadBitmapPtr,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
          FloatingActionButton(
            backgroundColor: Colors.lightGreen[300],
//            onPressed: _delete,
            onPressed: () async {
              await Hello.tmpTest();
            },
            tooltip: 'Increment',
            child: Icon(Icons.close),
          ),
        ],
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

class PixelMemoryImage extends ImageProvider<PixelMemoryImage> {
  PixelMemoryImage(this.bytes, this.width, this.height, this.format);

  final Uint8List bytes;
  final int width;
  final int height;
  final ui.PixelFormat format;

  @override
  Future<PixelMemoryImage> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<PixelMemoryImage>(this);
  }

  @override
  ImageStreamCompleter load(PixelMemoryImage key) {
    Completer<ui.Image> completer = Completer<ui.Image>();
    ui.decodeImageFromPixels(bytes, width, height, format, completer.complete);
    return OneFrameImageStreamCompleter(completer.future.then((ui.Image image) => ImageInfo(image: image)));
  }
}
